package com.woniu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.client.AccountClient;
import com.woniu.client.param.UpdateVenueStateParam;
import com.woniu.commons.exception.VenueRuntimeException;
import com.woniu.commons.model.RedisKey;
import com.woniu.commons.model.StateData;
import com.woniu.commons.util.GaudMapUtil;
import com.woniu.dao.YQualificationMapper;
import com.woniu.dao.YVenueBaseMapper;
import com.woniu.model.param.AddQualificationParam;
import com.woniu.model.form.PageQualificationForm;
import com.woniu.model.form.RejectQualificationForm;
import com.woniu.model.model.YQualification;
import com.woniu.model.model.YVenue;
import com.woniu.model.model.YVenueBase;
import com.woniu.model.param.PageQualificationByVenueIdParam;
import com.woniu.service.YQualificationService;
import io.seata.spring.annotation.GlobalTransactional;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author EdisonLiu
 * @since 2024年05月23日
 */
@Service
public class YQualificationServiceImpl extends ServiceImpl<YQualificationMapper, YQualification> implements YQualificationService {

    @Resource
    private YQualificationMapper qualificationMapper;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private AccountClient accountClient;
    @Resource
    private YVenueBaseMapper venueBaseMapper;
    @Autowired
    private GaudMapUtil gaudMapUtil;



    @Override
    public Integer addQualification(AddQualificationParam param) {


        RLock fairLock = redissonClient.getFairLock(RedisKey.venueQualificationVenueIdLock(param.getVenueId()));
        RLock lock = redissonClient.getMultiLock(fairLock);
        Integer i = 0;
        try {
            List<YQualification> qualifications = qualificationMapper.selectList(new QueryWrapper<YQualification>().eq("venue_id", param.getVenueId()).eq("certify_state", StateData.CERTIFY_STATE_WAIT_PASS));
            if (qualifications.size() != 0) {
                throw new VenueRuntimeException(3001, "请勿重复提交入驻申请");
            }
            // 尝试获取锁，最多等待20s
            boolean success = lock.tryLock(20, TimeUnit.SECONDS);
            if (success) {
                YQualification qualification = BeanUtil.toBean(param, YQualification.class);
                qualification.setCertifyState(StateData.CERTIFY_STATE_WAIT_PASS);

                i = qualificationMapper.insert(qualification);
            } else {
                throw new Exception("服务器繁忙");
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //释放锁
            lock.unlock();
            return i;
        }

    }

    @Override
    public Integer cancelQualification(Integer venueId, Integer certifyId) {


        RLock fairLock = redissonClient.getFairLock(RedisKey.venueQualificationUpdateLock(certifyId));
        RLock lock = redissonClient.getMultiLock(fairLock);
        Integer i = 0;
        try {
            // 尝试获取锁，最多等待20s
            boolean success = lock.tryLock(20, TimeUnit.SECONDS);
            if (success) {
                YQualification qualification = qualificationMapper.selectOne(new QueryWrapper<YQualification>().eq("certify_id", certifyId).eq("venue_id", venueId).eq("certify_state", StateData.CERTIFY_STATE_WAIT_PASS));
                if (qualification == null) {
                    throw new VenueRuntimeException(3002, "该入驻申请状态异常");
                }
                YQualification q = new YQualification();
                q.setCertifyId(certifyId);
                q.setCertifyState(StateData.CERTIFY_STATE_CANCEL);
                i = qualificationMapper.updateById(q);
            } else {
                throw new Exception("服务器繁忙");
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //释放锁
            lock.unlock();
        }
        return i;
    }

    @Override
    public Page pageQualification(PageQualificationForm form) {
        form.setPageNUm(form.getPageNUm() == null ? 1 : form.getPageNUm());
        form.setPageSize(form.getPageSize() == null ? 5 : form.getPageSize());

        Page<YQualification> page = new Page<>(form.getPageNUm(), form.getPageSize());
        QueryWrapper<YQualification> wrapper = new QueryWrapper<>();
        if (form.getCertifyState() != null) {
            if (form.getCertifyState().equals(StateData.CERTIFY_STATE_WAIT_PASS)) {
                wrapper.eq("certify_state", StateData.CERTIFY_STATE_WAIT_PASS);
            } else if (form.getCertifyState().equals(StateData.CERTIFY_STATE_PASS)) {
                wrapper.eq("certify_state", StateData.CERTIFY_STATE_PASS);
            } else {
                wrapper.eq("certify_state", StateData.CERTIFY_STATE_REJECT);
            }
        }
        Page<YQualification> page1 = qualificationMapper.selectPage(page, wrapper);
        return page1;
    }

    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public Integer passQualification(Integer certifyId) {
        RLock fairLock = redissonClient.getFairLock(RedisKey.venueQualificationUpdateLock(certifyId));
        RLock lock = redissonClient.getMultiLock(fairLock);
        Integer i = 0;
        try {
            // 尝试获取锁，最多等待20s
            boolean success = lock.tryLock(20, TimeUnit.SECONDS);
            if (success) {
                YQualification qualification = qualificationMapper.selectOne(new QueryWrapper<YQualification>().eq("certify_id", certifyId).eq("certify_state", StateData.CERTIFY_STATE_WAIT_PASS));
                if (qualification == null) {
                    throw new VenueRuntimeException(3002, "该入驻申请状态异常");
                }
                qualification.setCertifyState(StateData.CERTIFY_STATE_PASS);
                qualification.setApproveTime(LocalDateTime.now());
                i = qualificationMapper.updateById(qualification);

                UpdateVenueStateParam param = new UpdateVenueStateParam();
                param.setVenueState(2);
                param.setVenueId(qualification.getVenueId());

                accountClient.updateVenueState(param);


                //调用高德地图根据输入地址名，拆分经度纬度
                try {
                    Map<String,String> map = gaudMapUtil.getLonAndLat(qualification.getVenueAddress(), "c523bd172eed0a9fbd221d0e34663da7");
                    String longitude = map.get("lng");
                    String latitude = map.get("lat");

                    //新增场馆详细表
                    YVenueBase venueBase = new YVenueBase();
                    venueBase.setVenueId(qualification.getVenueId());
                    venueBase.setVenueName(qualification.getVenueName());
                    venueBase.setVenueImage(qualification.getVenueImg());
                    venueBase.setVenueLicense(qualification.getVenueLicense());
                    venueBase.setVenueDetails(qualification.getVenueDetails());
                    venueBase.setBusinessState(StateData.VENUE_STATE_OK);
                    venueBase.setVenueState(StateData.VENUE_STATE_OK);
                    venueBase.setVenueAddress(qualification.getVenueAddress());
                    venueBase.setLongitude(longitude);
                    venueBase.setLatitude(latitude);
                    venueBaseMapper.insert(venueBase);
                }catch (Exception e){
                    e.printStackTrace();
                }





            } else {
                throw new Exception("服务器繁忙");
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //释放锁
            lock.unlock();
        }
        return i;

    }

    @Override
    public Integer RejectQualificationForm(RejectQualificationForm form) {

        RLock fairLock = redissonClient.getFairLock(RedisKey.venueQualificationUpdateLock(form.getCertifyId()));
        RLock lock = redissonClient.getMultiLock(fairLock);
        Integer i = 0;
        try {
            // 尝试获取锁，最多等待20s
            boolean success = lock.tryLock(20, TimeUnit.SECONDS);
            if (success) {
                YQualification qualification = qualificationMapper.selectOne(new QueryWrapper<YQualification>().eq("certify_id", form.getCertifyId()).eq("certify_state", StateData.CERTIFY_STATE_WAIT_PASS));
                if (qualification == null) {
                    throw new VenueRuntimeException(3002, "该入驻申请状态异常");
                }
                qualification.setCertifyState(StateData.CERTIFY_STATE_REJECT);
                qualification.setRefuseCause(form.getRefuseCause());
                i = qualificationMapper.updateById(qualification);


                UpdateVenueStateParam param = new UpdateVenueStateParam();
                param.setVenueState(3);
                param.setVenueId(qualification.getVenueId());

                accountClient.updateVenueState(param);
            } else {
                throw new Exception("服务器繁忙");
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //释放锁
            lock.unlock();
        }
        return i;

    }

    /**
     * 场馆分页查询认证信息
     * @param param
     * @return
     */
    @Override
    public Page<YQualification> pageQualificationByVenueId(PageQualificationByVenueIdParam param) {
        param.setPageNum(param.getPageNum() == null ? 1 : param.getPageNum());
        param.setPageSize(param.getPageSize() == null ? 5 : param.getPageSize());
        Page<YQualification> page = new Page<>(param.getPageNum(), param.getPageSize());
        QueryWrapper<YQualification> wrapper = new QueryWrapper<>();
        wrapper.eq("venue_id",param.getVenueId());
        if (param.getCertifyState() != null){
            wrapper.eq("certify_state",param.getCertifyState());
        }
        Page<YQualification> yQualificationPage = qualificationMapper.selectPage(page, wrapper);
        return yQualificationPage;
    }
}
